#!/bin/bash

# Dependencies
# perl
# bc
# hexdump
# grep
# sed

rm temp temp1 >&- 2>&-

echo ""
echo "------------------------------------------------"
echo "    Riivolution XML to Gecko-code type file     "
echo "With aditional info printing for troubleshooting"
echo "------------------------------------------------"
echo ""

echo XML file path? Example: \"folder/name.xml\"
read xml

if ! test -f $xml ; then

	echo ""
	echo No XML file found.
	echo Exiting...
	exit 0

fi

grep -e memory -e patch $xml > temp

dos2unix temp >&- 2>&-

sed -i 's/<!--.*-->//' temp
sed -i '/^[[:space:]]*$/d' temp

echo ""

echo Does it come with an ASM binaries folder? \(y/n\)
read asmyn

echo ""

if [ "$asmyn" = y ]; then

	echo ASM folder path? Example: \"folder/ASM/\"
	read asmpath

		if ! [ -d "$asmpath" ]; then

		echo ""
		echo ASM folder not found.
		echo Exiting...
		exit 0

		fi

	echo ""

elif ! [ "$asmyn" = n ]; then

	echo Invalid option.
	echo Exiting...
	exit 0

fi

echo Keep aditional information? \(y/n\)
read infoyn
echo ""

if ! [ "$infoyn" = n -o "$infoyn" = y ]; then

	echo Invalid option.
	echo Exiting...
	exit 0

fi

echo Detecting regions...

grep "<region" $xml | grep -oP '(?<=").*?(?=")' > temp1

regnum=$( cat temp1 | sed -n '$=' )
reglist=$( cat temp1 | sed s/^$// )

echo ""
echo Detected $regnum regions: $reglist

for b in $( eval echo {1..$regnum} )
do

	reg=$( sed -n "$b"p temp1 )
	echo ""
	echo Starting $reg region...
	echo ""	
	echo Creating output$reg.txt file...

	touch output$reg.txt

	lnum=$( sed -n '$=' temp )

	for i in $( eval echo {1..$lnum} )
	do

		line=$( sed -n "$i"p temp )
		set $line
		
		# tag is to check for the "memory" or "patch" lines on the riivolution XML file
		
		tag=$( echo $line | grep -oP "(?<=<).*?(?= )" )
		
		if [ "$tag" = 'memory' ]; then
		
			# tag finds "memory" line
			# check target region code to see if it matches the region of the gecko code list
		
			target=$( echo $line | grep -oP '(?<=target=").*?(?=")' )
			
			# if target is different than gecko code list region then skip the line
			
			if ! [ "$target" = "$reg" -o "$target" = "" ]; then	continue; fi
			
			# if target is equal to gecko code list region or empty then proceed
			
			# valuefile name
			valuefile=$( echo $line | grep -oP '(?<=valuefile=").*?(?=")' |  sed "s/^.*\///" | sed "s/{\$__region}/$reg/" )
			# offset value
			offset=$( echo $line | grep -oP '(?<=offset=").*?(?=")' | sed 's/0x80//' | sed 's/.*/&/' | tr [:lower:] [:upper:] )
			# value tag value
			value=$( echo $line | grep -oP '(?<=value=").*?(?=")' | tr [:lower:] [:upper:] )
			# original condition value
			original=$( echo $line | grep -oP '(?<=original=").*?(?=")' | tr [:lower:] [:upper:] )
			# if value is a pointer it starts with the 8000 digit
			pointer=$( echo $value | sed "s/8000.*/8000/" )
			
			# digit length of "value" variable
			
			valsize=${#value}
			
			# value greater than 8 digits
			
			if [ "$valsize" -gt 8 ]; then
				
				offset_for_value_gt8=$( echo "ibase=16;$offset+4000000" | bc )
				
				number_of_lines=$( sed -n '$=' output$reg.txt )
				
				# if first memory patch is a value longer than 8 digits
				
				if [ "$number_of_lines" == "" ]; then number_of_lines=0; fi
				
				echo "$value"| fold -w8 >> output$reg.txt
				after_fold_number_of_lines=$( sed -n '$=' output$reg.txt )
				
				echo Adding value = "$value"
				
				let valuefile_fold_line_length=$after_fold_number_of_lines-$number_of_lines
				
				for (( a = 0, number_of_lines++; a < valuefile_fold_line_length ; a++, number_of_lines++ ))
				do
					
					next_offset=$( echo "ibase=10;obase=16;$offset_for_value_gt8+($a)*4" | bc )
					set $next_offset
					
					sed -i "$number_of_lines s/^/0$next_offset /" output$reg.txt
					
				done
			
			# value is a valuefile (BIN)
			
			elif ! [ -z "$valuefile" ]; then
			
				offset_for_valuefile=$( echo "ibase=16;$offset+4000000" | bc )
			
				number_of_lines=$( sed -n '$=' output$reg.txt )
				
				# if first memory patch is a BIN file
				
				if [ "$number_of_lines" == "" ]; then number_of_lines=0; fi
				
				hexdump -e '16/1 "%02x ""\n"' -v $asmpath$valuefile | tr --delete ' ' | perl -ne 'print uc' | fold -w8 >> output$reg.txt
				after_fold_number_of_lines=$( sed -n '$=' output$reg.txt )
				
				let valuefile_fold_line_length=$after_fold_number_of_lines-$number_of_lines
				
				echo Adding $valuefile...
				
				for (( a = 0, number_of_lines++; a < valuefile_fold_line_length ; a++, number_of_lines++ ))
				do
					
					next_offset=$( echo "ibase=10;obase=16;$offset_for_valuefile+($a*4)" | bc )
					set $next_offset
					
					sed -i "$number_of_lines s/^/0$next_offset /" output$reg.txt
					
				done
			
			# value is 8 digits long
			
			elif [ "$valsize" -eq 8 ]; then
			
				offset_8digits=$( echo "04$offset" )
				value_8digits=$( echo $value )
				echo Adding value = "$value_8digits"
				echo "$offset_8digits $value_8digits" >> output$reg.txt
			
			# value is 4 digits long
			
			elif [ "$valsize" -eq 4 ]; then
				
				offset_4digits=$( echo "02$offset" )
				value_4digits=$( echo "0000$value" )
				echo Adding value = "$value_4digits"
				echo "$offset_4digits $value_4digits" >> output$reg.txt
				
			# value is 2 digits long
			
			elif [ "$valsize" -eq 2 ]; then
			
				offset_2digits=$( echo "00$offset" )
				value_2digits=$( echo "000000$value" )
				echo Adding value = "$value_2digits"
				echo "$offset_2digits $value_2digits" >> output$reg.txt
			
			fi
		
			lnum4=$( sed -n '$=' output$reg.txt )
			
			# original, pointer, and target condition checks to print more info
			
			if ! [ -z "$original" ]; then

				sed -i "$lnum4 s/$/ : Original condition = $original/" output$reg.txt
				
			fi
		
			if [ "$pointer" = "8000" ]; then

				if [ "$valsize" -gt 8 ]; then
				
					let fixln1=$lnum4-$lnum2+1
					sed -i "$fixln1 s/$/ : ASM pointer = $value/" output$reg.txt
				
				elif [ "$valsize" -eq 8 ]; then
				
					sed -i "$lnum4 s/$/ : ASM pointer = $value/" output$reg.txt		
				
				fi
			
			fi
		
			if ! [ -z "$target" ]; then
		
				sed -i "$lnum4 s/$/ : Target = $target/" output$reg.txt
			
			fi
		
		elif [ "$tag" = 'patch' ]; then
		
			# tag finds "patch" line
			# is it the right "patch" line? "/>" must not be present on line
			
			patch_cond=$(echo $line | grep "/>")
		
			if ! [ "$patch_cond" = '' ]; then continue; fi
			
			patchid=$( echo $line | grep -oP '(?<=id=").*?(?=")' )
			
			echo ""
			echo "- Patch ID = $patchid"
			
		fi
		
	done

	echo ""

	echo -- output$reg.txt created.

done

echo ""

if [ "$infoyn" = n ]; then

	echo Removing information...
	sed -i "s/ :.*//" *.txt
	echo ""
	
fi

unix2dos *.txt >&- 2>&-

rm temp temp1

echo 'Exiting...'

exit 0
